package handlers

import (
	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/sirupsen/logrus"
	"github.com/yourusername/virt-manager-go/internal/models"
	"github.com/yourusername/virt-manager-go/internal/service"
	libvirtlib "libvirt.org/go/libvirt"
)

// NetworkHandler handles network requests
type NetworkHandler struct {
	connMgr *service.ConnectionManager
	log     *logrus.Logger
}

// NewNetworkHandler creates a new network handler
func NewNetworkHandler(connMgr *service.ConnectionManager, log *logrus.Logger) *NetworkHandler {
	return &NetworkHandler{
		connMgr: connMgr,
		log:     log,
	}
}

// ListNetworks returns all networks
//
//	@Summary		List networks
//	@Description	Returns all virtual networks for a specific connection
//	@Tags			networks
//	@Accept			json
//	@Produce		json
//	@Param			connection	query		string					false	"Connection ID"
//	@Success		200			{object}	map[string]interface{}	"{"networks": []models.NetworkSummary, "count": int}"
//	@Failure		500			{object}	map[string]interface{}	"Internal Server Error"
//	@Router			/networks [get]
func (h *NetworkHandler) ListNetworks(c *gin.Context) {
	conn, err := getConnectionFromRequest(c, h.connMgr)
	if err != nil {
		h.log.WithError(err).Error("Failed to get connection")
		c.JSON(http.StatusInternalServerError, gin.H{"error": "connection not available"})
		return
	}

	hvConn := conn.GetConnect()
	networks, err := hvConn.ListAllNetworks(libvirtlib.CONNECT_LIST_NETWORKS_ACTIVE | libvirtlib.CONNECT_LIST_NETWORKS_INACTIVE)
	if err != nil {
		h.log.WithError(err).Error("Failed to list networks")
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	result := make([]models.NetworkSummary, 0, len(networks))
	for _, network := range networks {
		name, _ := network.GetName()
		uuid, _ := network.GetUUIDString()
		active, _ := network.IsActive()
		bridge, _ := network.GetBridgeName()

		result = append(result, models.NetworkSummary{
			Name:   name,
			UUID:   uuid,
			Active: active,
			Bridge: bridge,
		})

		if err := network.Free(); err != nil {
			// 记录错误但继续执行
			h.log.WithError(err).Warn("Failed to free network")
		}
	}

	c.JSON(http.StatusOK, gin.H{
		"networks": result,
		"count":    len(result),
	})
}

// GetNetwork returns a specific network
//
//	@Summary		Get network details
//	@Description	Returns detailed information about a specific virtual network
//	@Tags			networks
//	@Accept			json
//	@Produce		json
//	@Param			connection	query		string	true	"Connection ID"
//	@Param			name		query		string	true	"Network name"
//	@Success		200			{object}	models.NetworkDetail
//	@Failure		404			{object}	map[string]interface{}	"Network not found"
//	@Failure		500			{object}	map[string]interface{}	"Internal Server Error"
//	@Router			/network [get]
func (h *NetworkHandler) GetNetwork(c *gin.Context) {
	name := c.Query("name")
	if name == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "name query parameter is required"})
		return
	}

	conn, err := getConnectionFromRequest(c, h.connMgr)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "connection not available"})
		return
	}

	hvConn := conn.GetConnect()

	network, err := hvConn.LookupNetworkByName(name)
	if err != nil {
		h.log.WithError(err).WithField("name", name).Error("Network not found")
		c.JSON(http.StatusNotFound, gin.H{"error": "network not found"})
		return
	}
	defer func() {
		if err := network.Free(); err != nil {
			// 记录错误但继续执行
			h.log.WithError(err).Warn("Failed to free network")
		}
	}()

	uuid, _ := network.GetUUIDString()
	active, _ := network.IsActive()
	bridge, _ := network.GetBridgeName()
	xmlDesc, _ := network.GetXMLDesc(0)

	c.JSON(http.StatusOK, models.NetworkDetail{
		Name:      name,
		UUID:      uuid,
		Active:    active,
		Bridge:    bridge,
		XMLConfig: xmlDesc,
	})
}

// CreateNetwork creates a new network
//
//	@Summary		Create network
//	@Description	Creates a new virtual network
//	@Tags			networks
//	@Accept			json
//	@Produce		json
//	@Param			connection	query		string					false	"Connection ID"
//	@Param			xml_config	body		string					true	"Network XML configuration"
//	@Success		201			{object}	map[string]interface{}	"{"message": string}"
//	@Failure		400			{object}	map[string]interface{}	"Bad Request"
//	@Failure		500			{object}	map[string]interface{}	"Internal Server Error"
//	@Router			/networks [post]
func (h *NetworkHandler) CreateNetwork(c *gin.Context) {
	var req struct {
		XMLConfig string `json:"xml_config" binding:"required"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	conn, err := getConnectionFromRequest(c, h.connMgr)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "connection not available"})
		return
	}

	hvConn := conn.GetConnect()
	network, err := hvConn.NetworkDefineXML(req.XMLConfig)
	if err != nil {
		h.log.WithError(err).Error("Failed to create network")
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	defer func() {
		if err := network.Free(); err != nil {
			// 记录错误但继续执行
			h.log.WithError(err).Warn("Failed to free network")
		}
	}()

	name, _ := network.GetName()
	h.log.WithField("name", name).Info("Network created successfully")
	c.JSON(http.StatusCreated, gin.H{"message": "network created successfully"})
}

// DeleteNetwork deletes a network
//
//	@Summary		Delete network
//	@Description	Deletes a virtual network
//	@Tags			networks
//	@Accept			json
//	@Produce		json
//	@Param			connection	query		string					true	"Connection ID"
//	@Param			name		query		string					true	"Network name"
//	@Success		200			{object}	map[string]interface{}	"{"message": string}"
//	@Failure		404			{object}	map[string]interface{}	"Network not found"
//	@Failure		500			{object}	map[string]interface{}	"Internal Server Error"
//	@Router			/network [delete]
func (h *NetworkHandler) DeleteNetwork(c *gin.Context) {
	name := c.Query("name")
	if name == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "name query parameter is required"})
		return
	}

	conn, err := getConnectionFromRequest(c, h.connMgr)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "connection not available"})
		return
	}

	hvConn := conn.GetConnect()

	network, err := hvConn.LookupNetworkByName(name)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "network not found"})
		return
	}
	defer func() {
		if err := network.Free(); err != nil {
			// 记录错误但继续执行
			h.log.WithError(err).Warn("Failed to free network")
		}
	}()

	if err := network.Undefine(); err != nil {
		h.log.WithError(err).Error("Failed to delete network")
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	h.log.WithField("name", name).Info("Network deleted successfully")
	c.JSON(http.StatusOK, gin.H{"message": "network deleted successfully"})
}

// StartNetwork starts a network
//
//	@Summary		Start network
//	@Description	Starts a virtual network
//	@Tags			networks
//	@Accept			json
//	@Produce		json
//	@Param			connection	query		string					true	"Connection ID"
//	@Param			name		query		string					true	"Network name"
//	@Success		200			{object}	map[string]interface{}	"{"message": string}"
//	@Failure		404			{object}	map[string]interface{}	"Network not found"
//	@Failure		500			{object}	map[string]interface{}	"Internal Server Error"
//	@Router			/network/start [post]
func (h *NetworkHandler) StartNetwork(c *gin.Context) {
	name := c.Query("name")
	if name == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "name query parameter is required"})
		return
	}

	conn, err := getConnectionFromRequest(c, h.connMgr)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "connection not available"})
		return
	}

	hvConn := conn.GetConnect()

	network, err := hvConn.LookupNetworkByName(name)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "network not found"})
		return
	}
	defer func() {
		if err := network.Free(); err != nil {
			// 记录错误但继续执行
			h.log.WithError(err).Warn("Failed to free network")
		}
	}()

	if err := network.Create(); err != nil {
		h.log.WithError(err).Error("Failed to start network")
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	h.log.WithField("name", name).Info("Network started successfully")
	c.JSON(http.StatusOK, gin.H{"message": "network started successfully"})
}

// StopNetwork stops a network
//
//	@Summary		Stop network
//	@Description	Stops a virtual network
//	@Tags			networks
//	@Accept			json
//	@Produce		json
//	@Param			connection	query		string					true	"Connection ID"
//	@Param			name		query		string					true	"Network name"
//	@Success		200			{object}	map[string]interface{}	"{"message": string}"
//	@Failure		404			{object}	map[string]interface{}	"Network not found"
//	@Failure		500			{object}	map[string]interface{}	"Internal Server Error"
//	@Router			/network/stop [post]
func (h *NetworkHandler) StopNetwork(c *gin.Context) {
	name := c.Query("name")
	if name == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "name query parameter is required"})
		return
	}

	conn, err := getConnectionFromRequest(c, h.connMgr)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "connection not available"})
		return
	}

	hvConn := conn.GetConnect()

	network, err := hvConn.LookupNetworkByName(name)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "network not found"})
		return
	}
	defer func() {
		if err := network.Free(); err != nil {
			// 记录错误但继续执行
			h.log.WithError(err).Warn("Failed to free network")
		}
	}()

	if err := network.Destroy(); err != nil {
		h.log.WithError(err).Error("Failed to stop network")
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	h.log.WithField("name", name).Info("Network stopped successfully")
	c.JSON(http.StatusOK, gin.H{"message": "network stopped successfully"})
}

// ListNetworksDefault lists networks on default connection
func (h *NetworkHandler) ListNetworksDefault(c *gin.Context) {
	c.Params = append(c.Params, gin.Param{Key: "connection_id", Value: ""})
	h.ListNetworks(c)
}
